package org.example.com.service.impl;

import org.example.com.mapper.ChatMessageMapper;
import org.example.com.mapper.ChatSessionMapper;
import org.example.com.pojo.vo.ChatMessage;
import org.example.com.pojo.vo.ChatResponse;
import org.example.com.pojo.vo.ChatSession;
import org.example.com.service.ChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.example.com.pojo.House;
import org.example.com.service.RentalDataService;
import java.time.LocalDateTime;
import java.util.*;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.client.ResourceAccessException;

@Service
public class ChatServiceImpl implements ChatService {

    @Autowired
    private ChatSessionMapper chatSessionMapper;
    
    @Autowired
    private ChatMessageMapper chatMessageMapper;
    
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RentalDataService rentalDataService;
    
    @Value("${ai.chat.api.url}")
    private String chatApiUrl;
    
    @Value("${ai.chat.api.key}")
    private String chatApiKey;
    
    @Value("${ai.chat.api.model-id}")
    private String modelId;

    @Override
    @Transactional
    public ChatSession createSession(Integer userId, String title) {
        // 创建新的会话
        ChatSession session = new ChatSession();
        session.setId(UUID.randomUUID().toString());
        session.setUserId(userId);
        session.setTitle(title);
        session.setStatus("active");
        session.setCreatedAt(LocalDateTime.now());
        session.setUpdatedAt(LocalDateTime.now());
        
        chatSessionMapper.insert(session);
        
        // 创建系统初始消息
        ChatMessage systemMessage = new ChatMessage();
        systemMessage.setUserId(userId);
        systemMessage.setRole("assistant");
        systemMessage.setContent("您好！我是您的租房咨询助手，请问有什么可以帮助您的？");
        systemMessage.setSessionId(session.getId());
        systemMessage.setCreatedAt(LocalDateTime.now());
        
        chatMessageMapper.insert(systemMessage);
        
        return session;
    }

    @Override
    public List<ChatSession> getUserSessions(Integer userId) {
        return chatSessionMapper.findByUserId(userId);
    }

    @Override
    public ChatSession getSessionById(String sessionId) {
        return chatSessionMapper.findById(sessionId);
    }

    @Override
    public List<ChatMessage> getSessionMessages(String sessionId) {
        return chatMessageMapper.findBySessionId(sessionId);
    }

    @Override
    @Transactional
    public ChatResponse sendMessage(Integer userId, String sessionId, String message) {
        // 保存用户消息
        ChatMessage userMessage = new ChatMessage();
        userMessage.setUserId(userId);
        userMessage.setRole("user");
        userMessage.setContent(message);
        userMessage.setSessionId(sessionId);
        userMessage.setCreatedAt(LocalDateTime.now());
        
        chatMessageMapper.insert(userMessage);
        
        // 获取历史消息用于上下文
        List<ChatMessage> history = chatMessageMapper.findBySessionId(sessionId);
        
        // 检查是否需要重置会话
        boolean needReset = checkIfNeedReset(history);
        if (needReset) {
            // 如果检测到多次错误，清除历史错误消息，只保留用户最新的消息
            System.out.println("检测到多次API错误，重置会话历史...");
            
            // 删除所有助手的错误消息
            for (ChatMessage msg : history) {
                if (msg.getRole().equals("assistant") && 
                    (msg.getContent().contains("抱歉，AI服务暂时不可用") || 
                     msg.getContent().contains("系统繁忙") || 
                     msg.getContent().contains("API认证失败"))) {
                    chatMessageMapper.deleteById(msg.getId());
                }
            }
            
            // 重新获取清理后的历史
            history = chatMessageMapper.findBySessionId(sessionId);
        }
        
        // 调用AI API获取回复
        String aiReply = callAiChatApi(history, message);
        
        // 保存AI回复
        ChatMessage aiMessage = new ChatMessage();
        aiMessage.setUserId(userId);
        aiMessage.setRole("assistant");
        aiMessage.setContent(aiReply);
        aiMessage.setSessionId(sessionId);
        aiMessage.setCreatedAt(LocalDateTime.now());
        
        chatMessageMapper.insert(aiMessage);
        
        // 更新会话的更新时间
        ChatSession session = chatSessionMapper.findById(sessionId);
        if (session != null) {
            chatSessionMapper.updateStatus(sessionId, "active");
        }
        
        // 返回响应
        ChatResponse response = new ChatResponse();
        response.setSessionId(sessionId);
        response.setMessage(aiReply);
        response.setSuccess(true);
        
        return response;
    }
    
    /**
     * 检查是否需要重置会话历史
     * 如果连续出现多次错误消息，可能需要重置会话
     */
    private boolean checkIfNeedReset(List<ChatMessage> history) {
        int errorCount = 0;
        for (ChatMessage msg : history) {
            if (msg.getRole().equals("assistant") && 
                (msg.getContent().contains("抱歉，AI服务暂时不可用") || 
                 msg.getContent().contains("系统繁忙") || 
                 msg.getContent().contains("API认证失败"))) {
                errorCount++;
            }
        }
        // 如果有3次以上的错误消息，建议重置会话
        return errorCount >= 3;
    }

    @Override
    public void updateSessionTitle(String sessionId, String title) {
        chatSessionMapper.updateTitle(sessionId, title);
    }

    @Override
    public void archiveSession(String sessionId) {
        chatSessionMapper.updateStatus(sessionId, "archived");
    }

    @Override
    @Transactional
    public void deleteSession(String sessionId) {
        // 先删除会话中的所有消息
        chatMessageMapper.deleteBySessionId(sessionId);
        // 再删除会话本身
        chatSessionMapper.deleteById(sessionId);
    }
    
    /**
     * 调用AI聊天API
     * 
     * @param history 历史消息
     * @param message 当前消息
     * @return AI回复
     */
     @Retryable(
        value = {ResourceAccessException.class, org.springframework.web.client.HttpServerErrorException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    private String callAiChatApi(List<ChatMessage> history, String message) {
        try {
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + chatApiKey);
            headers.set("Accept", "application/json");
            
            // 构建请求体 - 豆包API格式
            Map<String, Object> requestBody = new HashMap<>();
            
            // 添加历史消息上下文
            List<Map<String, String>> messages = new ArrayList<>();
            
            // 添加系统消息
            Map<String, String> systemMsg = new HashMap<>();
            systemMsg.put("role", "system");

            // 获取租房数据摘要
            String rentalDataSummary = rentalDataService.getRentalDataSummary();
            
            // 构建系统提示词，包含数据库中的房源信息
            String systemPrompt = "你是一个专业的租房咨询助手，提供房源信息、预约看房、租赁流程等咨询服务。" +
                "请根据以下数据库中的真实房源信息回答用户问题。如果用户询问的房源信息不在数据中，" +
                "请明确告知用户你只能提供系统中已有的房源信息，并建议用户浏览更多房源。\n\n" +
                "房源数据库信息：\n" + rentalDataSummary;
            
            systemMsg.put("content", systemPrompt);
            messages.add(systemMsg);
            
            // 添加历史消息，但过滤掉错误消息
            int validMessageCount = 0;
            for (ChatMessage chatMessage : history) {
                // 跳过错误消息，避免将错误消息作为上下文
                if (chatMessage.getContent().contains("抱歉，AI服务暂时不可用") || 
                    chatMessage.getContent().contains("系统繁忙") ||
                    chatMessage.getContent().contains("API认证失败")) {
                    continue;
                }
                
                // 只添加最近的几条有效消息，避免超出token限制
                if (validMessageCount >= 5) break;
                
                Map<String, String> msg = new HashMap<>();
                msg.put("role", chatMessage.getRole().equals("assistant") ? "assistant" : "user");
                msg.put("content", chatMessage.getContent());
                messages.add(msg);
                validMessageCount++;
            }
            
            // 添加当前用户消息
            Map<String, String> userMsg = new HashMap<>();
            userMsg.put("role", "user");

            
            // 分析用户消息，获取相关的房源数据
            String enhancedMessage = message;
            String rentalData = getRentalDataForQuery(message);
            if (rentalData != null && !rentalData.isEmpty()) {
                enhancedMessage = message + "\n\n[系统提供的房源数据]:\n" + rentalData;
            }
            
            userMsg.put("content", enhancedMessage);
            messages.add(userMsg);
            
            requestBody.put("messages", messages);
            requestBody.put("model", modelId);
            requestBody.put("temperature", 0.7);
            requestBody.put("stream", false);
            
            // 发送请求前记录日志
            System.out.println("发送请求到豆包API: " + chatApiUrl);
            System.out.println("请求头: " + headers);
            System.out.println("请求体: " + requestBody);
            
            // 发送请求
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
            ResponseEntity<Map> response = restTemplate.postForEntity(chatApiUrl, request, Map.class);
            
            // 记录响应日志
            System.out.println("豆包API响应状态: " + response.getStatusCode());
            System.out.println("豆包API响应体: " + response.getBody());
            
            // 处理响应
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Map<String, Object> choices = (Map<String, Object>) ((List) response.getBody().get("choices")).get(0);
                Map<String, String> message_obj = (Map<String, String>) choices.get("message");
                return message_obj.get("content");
            } else {
                return "抱歉，我暂时无法回答您的问题，请稍后再试。";
            }
        } catch (org.springframework.web.client.HttpClientErrorException e) {
            // 处理HTTP错误，如404、401等
            e.printStackTrace();
            String errorMessage = "API请求失败: " + e.getStatusCode();
            if (e.getStatusCode().value() == 404) {
                errorMessage = "API地址不存在，请检查配置是否正确。";
            } else if (e.getStatusCode().value() == 401) {
                errorMessage = "API认证失败，请检查API密钥是否正确。";
            } else if (e.getStatusCode().value() == 403) {
                errorMessage = "API访问被拒绝，请检查权限设置。";
            }
            System.err.println("火山引擎豆包API调用失败: " + errorMessage);
            return "抱歉，AI服务暂时不可用。请联系管理员检查API配置。";
        } catch (org.springframework.web.client.HttpServerErrorException e) {
            // 处理服务器错误，如500等
            e.printStackTrace();
            String responseBody = e.getResponseBodyAsString();
            System.err.println("火山引擎豆包API服务器错误: " + e.getStatusCode() + ", 响应: " + responseBody);
            
            // 尝试解析错误响应
            String errorMessage = "服务器内部错误，请稍后再试。";
            if (responseBody.contains("InternalServiceError")) {
                errorMessage = "AI服务内部错误，请稍后再试。";
                // 如果是重复的错误消息，可能是历史记录问题，尝试清空历史
                if (history.size() > 2) {
                    System.out.println("检测到可能的历史记录问题，建议清空历史记录后重试。");
                }
            }
            
            return "抱歉，" + errorMessage;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("火山引擎豆包API调用异常: " + e.getMessage());
            return "系统繁忙，请稍后再试。";
        }
    }

     /**
     * 当所有重试都失败时的恢复方法
     * 
     * @param e 异常
     * @param history 历史消息
     * @param message 当前消息
     * @return 默认的AI回复
     */
    @Recover
    private String recoverFromApiFailure(Exception e, List<ChatMessage> history, String message) {
        System.err.println("所有重试尝试都失败了，执行恢复方法: " + e.getMessage());
        e.printStackTrace();
        
        // 尝试提供一些基本的回复，基于本地数据
        if (message.toLowerCase().contains("房源") || 
            message.toLowerCase().contains("租金") || 
            message.toLowerCase().contains("价格")) {
            
            try {
                // 尝试从本地数据库获取一些房源信息
                List<House> houses = rentalDataService.getPopularHouses(3);
                if (houses != null && !houses.isEmpty()) {
                    return "抱歉，AI服务暂时不可用，但我可以为您提供一些热门房源信息：\n\n" +
                           rentalDataService.formatHouseList(houses) +
                           "\n如需更多信息，请稍后再试。";
                }
            } catch (Exception ex) {
                // 忽略本地数据获取的错误
            }
        }
        
        return "抱歉，我暂时无法连接到AI服务。请稍后再试或联系客服获取帮助。";
    }

    
    /**
     * 根据用户查询获取相关的房源数据
     * 
     * @param query 用户查询
     * @return 相关的房源数据文本
     */
    private String getRentalDataForQuery(String query) {
        // 小写化查询，便于匹配
        String lowerQuery = query.toLowerCase();
        
        try {
            // 检查是否是价格相关查询
            if (lowerQuery.contains("价格") || lowerQuery.contains("租金") || 
                lowerQuery.contains("多少钱") || lowerQuery.contains("价位") || 
                lowerQuery.contains("元") || lowerQuery.contains("便宜") || 
                lowerQuery.contains("贵")) {
                
                // 尝试提取价格范围
                String minPrice = null;
                String maxPrice = null;
                
                // 简单的价格范围提取，实际应用可能需要更复杂的NLP
                if (lowerQuery.contains("低于") || lowerQuery.contains("不超过") || lowerQuery.contains("以下")) {
                    maxPrice = extractNumber(lowerQuery);
                } else if (lowerQuery.contains("高于") || lowerQuery.contains("至少") || lowerQuery.contains("以上")) {
                    minPrice = extractNumber(lowerQuery);
                } else if (lowerQuery.contains("到") || lowerQuery.contains("至") || lowerQuery.contains("-")) {
                    // 尝试提取范围，如"2000到3000"
                    String[] numbers = extractNumberRange(lowerQuery);
                    if (numbers != null && numbers.length >= 2) {
                        minPrice = numbers[0];
                        maxPrice = numbers[1];
                    }
                }
                
                // 如果提取到价格范围，查询相应的房源
                if (minPrice != null || maxPrice != null) {
                    List<House> houses = rentalDataService.getHousesByPriceRange(minPrice, maxPrice);
                    return rentalDataService.formatHouseList(houses);
                }
            }
            
            // 检查是否是区域相关查询
            if (lowerQuery.contains("区") || lowerQuery.contains("地段") || 
                lowerQuery.contains("位置") || lowerQuery.contains("在哪") || 
                lowerQuery.contains("地方")) {
                
                // 提取可能的区域名称
                String district = extractDistrict(lowerQuery);
                if (district != null) {
                    List<House> houses = rentalDataService.getHousesByDistrict(district);
                    return rentalDataService.formatHouseList(houses);
                }
            }
            
            // 检查是否是特定房源查询
            if (lowerQuery.contains("房源") || lowerQuery.contains("房子") || 
                lowerQuery.contains("公寓") || lowerQuery.contains("单间") || 
                lowerQuery.contains("推荐") || lowerQuery.contains("有什么") || 
                lowerQuery.contains("介绍")) {
                
                // 提取可能的关键词
                String keyword = extractKeyword(lowerQuery);
                if (keyword != null) {
                    List<House> houses = rentalDataService.searchHousesByKeyword(keyword);
                    return rentalDataService.formatHouseList(houses);
                } else {
                    // 如果没有明确关键词，返回热门房源
                    List<House> houses = rentalDataService.getPopularHouses(5);
                    return rentalDataService.formatHouseList(houses);
                }
            }
            
            // 如果是具体房源ID的查询
            if (lowerQuery.contains("房源id") || lowerQuery.contains("编号")) {
                Integer houseId = extractHouseId(lowerQuery);
                if (houseId != null) {
                    House house = rentalDataService.getHouseDetail(houseId);
                    return rentalDataService.formatHouseInfo(house);
                }
            }
            
            // 如果是一般性问题，不需要特定数据，返回null
            return null;
            
        } catch (Exception e) {
            System.err.println("获取房源数据时出错: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 从文本中提取数字
     */
    private String extractNumber(String text) {
        // 简单实现，仅提取第一个数字
        StringBuilder number = new StringBuilder();
        boolean foundDigit = false;
        
        for (char c : text.toCharArray()) {
            if (Character.isDigit(c)) {
                number.append(c);
                foundDigit = true;
            } else if (foundDigit && !Character.isDigit(c)) {
                break;
            }
        }
        
        return foundDigit ? number.toString() : null;
    }
    
    /**
     * 从文本中提取数字范围
     */
    private String[] extractNumberRange(String text) {
        // 简单实现，提取形如"2000到3000"的范围
        String[] parts = text.split("到|至|-");
        if (parts.length < 2) return null;
        
        String[] result = new String[2];
        
        // 提取第一个部分中的数字
        StringBuilder number1 = new StringBuilder();
        boolean foundDigit1 = false;
        for (char c : parts[0].toCharArray()) {
            if (Character.isDigit(c)) {
                number1.append(c);
                foundDigit1 = true;
            } else if (foundDigit1 && !Character.isDigit(c)) {
                break;
            }
        }
        
        // 提取第二个部分中的数字
        StringBuilder number2 = new StringBuilder();
        boolean foundDigit2 = false;
        for (char c : parts[1].toCharArray()) {
            if (Character.isDigit(c)) {
                number2.append(c);
                foundDigit2 = true;
            } else if (foundDigit2 && !Character.isDigit(c)) {
                break;
            }
        }
        
        if (foundDigit1 && foundDigit2) {
            result[0] = number1.toString();
            result[1] = number2.toString();
            return result;
        }
        
        return null;
    }
    
    /**
     * 从文本中提取区域名称
     */
    private String extractDistrict(String text) {
        // 常见的区名列表，实际应用中可以从数据库获取
        String[] districts = {"朝阳", "海淀", "东城", "西城", "丰台", "石景山", "通州", "昌平", 
                             "大兴", "顺义", "房山", "门头沟", "平谷", "怀柔", "密云", "延庆"};
        
        for (String district : districts) {
            if (text.contains(district)) {
                return district;
            }
        }
        
        return null;
    }
    
    /**
     * 从文本中提取关键词
     */
    private String extractKeyword(String text) {
        // 简单实现，提取可能的关键词
        String[] keywords = {"单间", "合租", "整租", "公寓", "两居", "三居", "精装", "近地铁", "带阳台", "带家具"};
        
        for (String keyword : keywords) {
            if (text.contains(keyword)) {
                return keyword;
            }
        }
        
        return null;
    }
    
    /**
     * 从文本中提取房源ID
     */
    private Integer extractHouseId(String text) {
        // 提取形如"房源ID: 123"或"编号123"的ID
        int idIndex = text.indexOf("ID");
        if (idIndex == -1) {
            idIndex = text.indexOf("编号");
        }
        
        if (idIndex != -1) {
            StringBuilder id = new StringBuilder();
            boolean foundDigit = false;
            
            for (int i = idIndex + 1; i < text.length(); i++) {
                char c = text.charAt(i);
                if (Character.isDigit(c)) {
                    id.append(c);
                    foundDigit = true;
                } else if (foundDigit && !Character.isDigit(c)) {
                    break;
                }
            }
            
            if (foundDigit) {
                try {
                    return Integer.parseInt(id.toString());
                } catch (NumberFormatException e) {
                    return null;
                }
            }
        }
        
        return null;
    }
}
